#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QMutex>
#include <QDateTime>

// 日志级别枚举
enum class LogLevel {
    Debug,
    Info,
    Warning,
    Critical,
    Fatal
};

class Logger {
public:
    // 获取单例
    static Logger& instance() {
        static Logger logger;
        return logger;
    }

    // 配置日志输出位置
    void setOutputTargets(bool toConsole, bool toFile, const QString& filePath = "") {
        QMutexLocker locker(&mutex);
        outputToConsole = toConsole;
        outputToFile = toFile;
        
        if (toFile && !filePath.isEmpty()) {
            openLogFile(filePath);
        } else {
            closeLogFile();
        }
    }

    // 设置最低输出日志级别
    void setLogLevel(LogLevel level) {
        QMutexLocker locker(&mutex);
        minLogLevel = level;
    }

    // 自定义消息处理函数
    static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
        LogLevel level = logLevelFromQtMsgType(type);
        
        // 过滤低于设定级别的日志
        if (level < instance().minLogLevel) {
            return;
        }
        
        QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
        QString logType = logTypeToString(level);
        QString location = QString("%1:%2").arg(context.file).arg(context.line);
        
        // 构建日志消息
        // QString logMessage = QString("[%1] [%2] [%3] %4")
        //     .arg(timestamp)
        //     .arg(logType)
        //     .arg(location)
        //     .arg(msg);
        QString logMessage = QString("[%1] [%2] %3")
            .arg(timestamp)
            .arg(logType)
            .arg(msg);
        
        // 输出到控制台
        if (instance().outputToConsole) {
            QByteArray consoleMsg = logMessage.toLocal8Bit() + "\n";
            fwrite(consoleMsg.constData(), 1, consoleMsg.length(), stderr);
        }
        
        // 输出到文件
        if (instance().outputToFile && instance().logFile.isOpen()) {
            QTextStream textStream(&instance().logFile);
            textStream << logMessage << "\n";
        }
        
        // 处理致命错误
        if (type == QtFatalMsg) {
            abort();
        }
    }

private:
    Logger() = default;
    ~Logger() { closeLogFile(); }
    
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;

    // 打开日志文件
    void openLogFile(const QString& filePath) {
        closeLogFile();
        
        logFile.setFileName(filePath);
        if (logFile.open(QIODevice::Append | QIODevice::Text)) {
            qDebug() << "日志文件已打开:" << filePath;
        } else {
            qWarning() << "无法打开日志文件:" << filePath;
        }
    }

    // 关闭日志文件
    void closeLogFile() {
        if (logFile.isOpen()) {
            logFile.close();
        }
    }

    // 将QtMsgType转换为LogLevel
    static LogLevel logLevelFromQtMsgType(QtMsgType type) {
        switch (type) {
            case QtDebugMsg: return LogLevel::Debug;
            case QtInfoMsg: return LogLevel::Info;
            case QtWarningMsg: return LogLevel::Warning;
            case QtCriticalMsg: return LogLevel::Critical;
            case QtFatalMsg: return LogLevel::Fatal;
            default: return LogLevel::Info;
        }
    }

    // 将LogLevel转换为字符串
    static QString logTypeToString(LogLevel level) {
        switch (level) {
            case LogLevel::Debug: return "DEBUG";
            case LogLevel::Info: return "INFO";
            case LogLevel::Warning: return "WARNING";
            case LogLevel::Critical: return "CRITICAL";
            case LogLevel::Fatal: return "FATAL";
            default: return "INFO";
        }
    }

private:
    QFile logFile;
    QMutex mutex;
    bool outputToConsole = true;
    bool outputToFile = false;
    LogLevel minLogLevel = LogLevel::Debug;
};